/**
 * Created by shenzhilin on 2017-7-7.
 */
function Authorization (authorizations, options) {
  this.init = (authorizations, options) => {
    this.authorizations = authorizations
    let theOpts = options || {}
    this.assert = theOpts['assert'] || ((authorization, target, roleOrPermission) => target === authorization)
    this.authorizationsContext = theOpts['context']
    this.disabled = theOpts['disabled'] || false
  }

  this.hasTrait = (trait, traitType) => {
    traitType = traitType || 'roles'
    let theAuth = this.authorizations
    if (typeof theAuth === 'function') {
      theAuth = this.authorizations(this.authorizationsContext)
    }
    if (theAuth && typeof theAuth[traitType]) {
      let theTraits = theAuth[traitType]
      if (typeof theTraits === 'string') {
        theTraits = theTraits.split[',']
      }
      if (!Array.isArray(theTraits)) {
        throw new Error(`权限中的${traitType}必须是字符串或字符串数组`)
      }
      return theTraits.some((theTrait) => {
        return this.disabled || this.assert(theTrait, trait, traitType)
      })
    }
    return false
  }

  this.init(authorizations, options)
}

Authorization.prototype.hasRole = function (role) {
  return this.hasTrait(role, 'roles')
}

Authorization.prototype.hasPermission = function (permission) {
  return this.hasTrait(permission, 'permissions')
}

Authorization.prototype.update = function ({authorizations, options}) {
  this.init(authorizations, options)
}

Authorization.prototype.disable = () => {
  this.disabled = true
}

Authorization.prototype.enable = () => {
  this.disabled = false
}

function install (Vue, settings) {
  if (install.installed) return
  install.installed = true
  settings = settings || {}
  let _authorization = new Authorization(settings['authorization'], settings['options'] || {})

  Vue.hasRole = r => _authorization.hasRole(r)
  Vue.hasPermission = p => _authorization.hasPermission(p)
  Vue.updateAuthorization = ({authorizations, options}) => _authorization.update({authorizations, options})

  Vue.directive('auth', {
    bind: function (el, binding) {
      let checkFunction = _authorization.hasPermission
      if (binding.arg === 'role') {
        checkFunction = _authorization.hasRole
      }
      if (!binding.arg && binding.arg !== '' && binding.arg !== 'permission') {
        throw new Error('指令参数错误')
      }
      if (!checkFunction(binding.value)) {
        el.parentNode.removeChild(el)
      }
    }
  })

  Object.defineProperty(Vue.prototype, '$authorization', {
    get () {
      return _authorization
    }
  })
}

export default { install }
